package com.pansoft.nfc.mifare.activity;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.efounder.chat.utils.CommonThreadPoolUtils;
import com.pansoft.nfc.NfcAlertUtils;
import com.pansoft.nfc.NfcWalletDeleteManager;
import com.pansoft.nfc.acs.ApduListManager;
import com.pansoft.nfc.mifare.Common;
import com.pansoft.nfc.mifare.MCManager;
import com.pansoft.nfc.mifare.MCReader;
import com.pansoft.openplanet.R;
import com.pansoft.openplanet.activity.TCBaseActivity;
import com.pansoft.openplanet.bean.CardBean;
import com.pansoft.openplanet.bean.CardWalletInfo;
import com.pansoft.openplanet.db.CardDao;
import com.pansoft.openplanet.widget.TCLoadingDataView;
import com.utilcode.util.ToastUtils;

import org.json.JSONObject;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.pansoft.nfc.NfcCommonUtils.getReadWalletPosition;

/**
 * 删除冷钱包，与nfc卡片通信
 *
 * @author wang
 */
public class MifareDeleteColdWalletActivity extends TCBaseActivity implements NfcWalletDeleteManager.INfcDeleteWalletListener {

    private TextView tvTitle;
    private TextView tvStatus;

    private Button btnWrite;

    private MCManager mcManager;
    private CardDao cardDao;
    private CardBean cardBean;

    private int position;
    private String[] positions;
    private List<CardWalletInfo> cardWalletInfoList;
    private String cardInfo = "";
    private String startString;

    /**
     * Nodes (stats) MCT passes through during its startup.
     * 一直循环调用
     * 是否有nfc-->是否支持m1卡-->是否启用nfc功能-->处理贴卡intent
     */
    private enum StartUpNode {
        HasNfc,
        HasMifareClassicSupport,
        HasNfcEnabled,
        HandleNewIntent
    }

    private Intent mOldIntent = null;

    public static void start(Context context, String cardNo, String address) {
        Intent starter = new Intent(context, MifareDeleteColdWalletActivity.class);
        starter.putExtra("address", address);
        starter.putExtra("cardNo", cardNo);
        context.startActivity(starter);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.open_planet_acitivty_blt_message);
        initView();
        showNfcConnecting();
        initData();
    }

    private void initView() {
        tvTitle = (TextView) findViewById(R.id.tv_title);
        tvStatus = (TextView) findViewById(R.id.tv_status);
        TextView tvHint = (TextView) findViewById(R.id.tv_hint);
        tvHint.setVisibility(View.GONE);

        btnWrite = (Button) findViewById(R.id.btn_write);
        btnWrite.setVisibility(View.GONE);
    }

    private void initData() {
        tvTitle.setText(R.string.open_planet_delete_card);
        btnWrite.setVisibility(View.GONE);
    }

    /**
     * Each phase of the MCTs startup is called "node" (see {@link StartUpNode})
     * and can be started by this function. The following nodes will be
     * started automatically (e.g. if the "has NFC support?" node is triggered
     * the "has MIFARE classic support?" node will be run automatically
     * after that).
     * 一直循环调用
     * 是否有nfc-->是否支持m1卡-->是否启用nfc功能-->处理贴卡intent
     *
     * @param startUpNode The node of the startup checks chain.
     * @see StartUpNode
     */
    private void runSartUpNode(StartUpNode startUpNode) {
        switch (startUpNode) {
            case HasNfc:
                Common.setNfcAdapter(NfcAdapter.getDefaultAdapter(this));
                if (Common.getNfcAdapter() == null) {
                    NfcAlertUtils.showNonEmptyCardAlert(MifareDeleteColdWalletActivity.this);
                } else {
                    runSartUpNode(StartUpNode.HasMifareClassicSupport);
                }
                break;
            case HasMifareClassicSupport:
                if (!Common.hasMifareClassicSupport(this)) {
                    NfcAlertUtils.createNfcEnableDialog(MifareDeleteColdWalletActivity.this);
                } else {
                    runSartUpNode(StartUpNode.HasNfcEnabled);
                }
                break;
            case HasNfcEnabled:
                Common.setNfcAdapter(NfcAdapter.getDefaultAdapter(this));
                if (!Common.getNfcAdapter().isEnabled()) {
                    NfcAlertUtils.createNfcEnableDialog(MifareDeleteColdWalletActivity.this);
                } else {
                    // NOTE: Use MCT with internal NFC controller.
                    Common.enableNfcForegroundDispatch(this);
                    runSartUpNode(StartUpNode.HandleNewIntent);
                }
                break;
            case HandleNewIntent:
                Common.setPendingComponentName(null);
                Intent intent = getIntent();
                if (intent != null && intent.getAction() != null) {
                    boolean isIntentWithTag = intent.getAction().equals(
                            NfcAdapter.ACTION_TECH_DISCOVERED);
                    if (isIntentWithTag && intent != mOldIntent) {
                        // If MCT was called by another app or the dispatch
                        // system with a tag delivered by intent, handle it as
                        // new tag intent.
                        mOldIntent = intent;
                        onNewIntent(getIntent());
                    } else {
                        // Last node. Do nothing.
                        break;
                    }
                }
                break;
        }
    }

    /**
     * Resume by triggering MCT's startup system
     * ({@link #runSartUpNode(StartUpNode)}).
     *
     * @see #runSartUpNode(StartUpNode)
     */
    @Override
    public void onResume() {
        super.onResume();
        runSartUpNode(StartUpNode.HasNfc);
    }


    /**
     * Disable NFC foreground dispatch system.
     *
     * @see Common#disableNfcForegroundDispatch(Activity)
     */
    @Override
    public void onPause() {
        Common.disableNfcForegroundDispatch(this);
        super.onPause();
    }

    /**
     * Handle new Intent as a new tag Intent and if the tag/device does not
     * support MIFARE Classic, then run {@link }.
     *
     * @see Common#treatAsNewTag(Intent, android.content.Context)
     * @see
     */
    @Override
    public void onNewIntent(Intent intent) {
        Log.d("onNewIntent", intent.getAction());
        int typeCheck = Common.treatAsNewTag(intent, this);
        if (typeCheck == -1 || typeCheck == -2) {
            // Device or tag does not support MIFARE Classic.
            // Run the only thing that is possible: The tag info tool.
            showNfcFail();
        } else {
            //读到卡片，开始操作
            showNfcConnectSuccess();
            readBegin();
        }
    }

    /**
     * Triggered by {@link #onActivityResult(int, int, Intent)}
     * this method starts a worker thread that first reads the tag and then
     * calls {@link #( SparseArray )}.
     */
    private void readBegin() {
        MCReader reader = Common.checkForTagAndCreateReader(this);
        if (reader == null) {
            showNfcFail();
            return;
        }
        mcManager = new MCManager(this, reader);
        mcManager.setMcStateListener(new MCManager.MCStateListener() {
            @Override
            public void onAuthSuccess(String cardNo, String cardType) {
                onCheckUid(cardNo, cardType);
            }

            @Override
            public void onAddSucceed() {

            }

            @Override
            public void onAddedAlready() {

            }

            @Override
            public void onError(String error) {
                showNfcFail();
            }
        });
        cardDao = new CardDao(this);
        mcManager.readUidSector();
    }

    /**
     * 检查uid
     *
     * @param cardNo hex十六进制数
     */
    private void onCheckUid(String cardNo, String cardType) {
        if (cardNo == null || "".equals(cardNo)) {
            showNfcFail();
            return;
        }
        try {
            //卡号
            cardNo = new String(Common.hexStringToByteArray(cardNo), StandardCharsets.UTF_8).trim();
            if (!cardNo.equals(getIntent().getStringExtra("cardNo"))) {
                showNfcFail();
                return;
            }
            cardBean = cardDao.getCardBean(cardNo);
            cardWalletInfoList = cardBean.getWalletInfoList();
            String startResponse = mcManager.readStartSector();
            JSONObject jsonObject = new JSONObject(startResponse);
            String positionString = jsonObject.optString("p");
            positions = positionString.split(",");
            dealDeleteCardInfo();
            CommonThreadPoolUtils.execute(new Runnable() {
                @Override
                public void run() {
                    new NfcWalletDeleteManager().deleteFromServer(MifareDeleteColdWalletActivity.this,
                            getIntent().getStringExtra("address"), cardBean, cardInfo);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void dealDeleteCardInfo() {
        int ver = 0;
        if (!"".equals(cardBean.getVersion())) {
            ver = Integer.valueOf(cardBean.getVersion()) + 1;
        }
        cardBean.setVersion(String.valueOf(ver));
        if (positions.length < 1) {
            return;
        }
        position = getReadWalletPosition(getIntent().getStringExtra("address"), cardWalletInfoList);
        StringBuilder sb = new StringBuilder();
        for (String s :
                positions) {
            if (Integer.valueOf(s) != position) {
                if (sb.length() > 0) {
                    sb.append(",");
                }
                sb.append(s);
            }
        }
        startString = ApduListManager.parseStartData(
                sb.toString(), String.valueOf(ver));
        Map<String, String> jsonMap = new HashMap<>();
        jsonMap.put("p", sb.toString());
        jsonMap.put("v", ver + "");
        JSONObject jsonObject = new JSONObject(jsonMap);
        cardInfo = jsonObject.toString();
    }

    private void deleteStartPosition() {
        //更新start区块信息，将删除钱包的pos删除掉
        if (mcManager.writeWallet(startString, 8, 1)) {
            //本地card数据库删除掉该钱包
            deleteWalletFromCardDb();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    ToastUtils.showShort(R.string.common_text_delete_success);
                    setResult(RESULT_OK);
                    finish();
                }
            });
        } else {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    showNfcFail();
                }
            });
        }
    }

    /**
     * 从card表中删除钱包
     */
    private void deleteWalletFromCardDb() {
        List<CardWalletInfo> cardWalletInfos = new ArrayList<>();
        for (CardWalletInfo c :
                cardWalletInfoList) {
            if (c.getInCardPosition() != position) {
                cardWalletInfos.add(c);
            }
        }
        cardBean.setWalletInfoList(cardWalletInfos);
        cardBean.setEnable(true);
        cardDao.insertOrReplace(cardBean);
    }

    @Override
    public void onDeleteFromServerSuccess() {

    }

    /**
     * 连接卡片
     */
    private void showNfcConnecting() {
        tvStatus.setText(R.string.op_put_card);
    }


    /**
     * 连接卡片成功
     */
    private void showNfcConnectSuccess() {
        tvStatus.setText(R.string.op_connect_card_success);
    }

    /**
     * 卡片操作失败
     */
    private void showNfcFail() {
        TCLoadingDataView.dismiss();
        tvStatus.setText(R.string.op_sth_wrong_put_card_again);
        new androidx.appcompat.app.AlertDialog.Builder(this).setTitle(R.string.common_text_hint)
                .setMessage(R.string.op_sth_wrong_put_card_again)
                .setCancelable(false)
                .setPositiveButton(R.string.common_text_confirm, null)
                .setNegativeButton(R.string.common_text_cancel, null)
                .create().show();
    }
}